home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 …SCII & the Runetime Code / ADC Developer CD (1992-07) (''Butch ASCII And The Runtime Code'')_iso / Dev.CD 199207.iso / Development Platforms / Apple II / HyperCardIIGS / Sample.XCMDs / XWindow Shell / XWindShell (C) / XWindShell.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-05  |  12.3 KB  |  362 lines  |  [TEXT/MPS ]

  1. /* ---------------------------------------------------------------------
  2.  
  3.    C source for XWindShell XCMD
  4.    
  5.    Copyright © 1989-92 Apple Computer, Inc.
  6.  
  7.  
  8.    This file includes the source code for the XWindShell XCMD.  While
  9.    this XCMD will compile and execute in its current form.  The XWindow
  10.    has no functionality beyond demonstrating the basics of HyperCard's
  11.    XWindow capabilities.  This file is meant to be a basis where an
  12.    XCMD author can "fill in the blanks" to create their XCMD.  See the
  13.    other sample XCMDs such as Picture, MemState, and ListWindow for
  14.    practical examples of code dealing with responding to XWindow events
  15.    and strategies for storing information for the XWindows while they
  16.    are open.
  17.  
  18.    The files included with the XWindShell XCMD are meant to be
  19.    used as a starting point for XCMDs in C or Pascal that wish to
  20.    create and manage XWindows.
  21.  
  22.    Files:
  23.    ------
  24.     *XWindShell.c
  25.      XWindShell.r
  26.      MakeFile
  27.     
  28.     
  29.    Author:        Darin Acquistapace
  30.    Created:        01/29/92
  31.    Modified:    See Mod History Below
  32.  
  33.    Modification History:
  34.    ---------------------
  35.      01/29/92 - New today.
  36.      
  37.    ------------------------------------------------------------------ */
  38.  
  39. #include <Types.h>
  40. #include <Memory.h>
  41. #include <MiscTool.h>
  42. #include <GSOS.h>
  43. #include <QuickDraw.h>
  44. #include <Resources.h>
  45. #include <QDAux.h>
  46. #include <Event.h>
  47. #include <Control.h>
  48. #include <Windows.h>
  49. #include <HyperXCMD.h>
  50.  
  51. /* Define any global variables here.  The makeFile instructs the linker
  52.    to link this segment after EntrySeg and Main. */
  53. Word        memoryID;
  54. XCMDPtr        gParamPtr;
  55.  
  56. /* Forward declarations */
  57. void CleanUpMemory();
  58. Boolean CorrectVersion();
  59. void HandleCursorWithin();
  60. void HandleEvents();
  61. void HandleHideShow();
  62. void HandleOpenEvent();
  63. void HandleWindowClick();
  64. void HTError();
  65. void MyDisposeHandle();
  66. void ProcessIdle();
  67. void ReturnResult();
  68. void SetUpContents();
  69. void UpdateXWindow();
  70. pascal void XWindShell();
  71.  
  72. /* The first segment in the XCMD, calls the main routine. */
  73. segment "EntrySeg";
  74. pascal void EntryPoint(paramPtr)
  75. XCMDPtr paramPtr;
  76. {
  77.   XWindShell(paramPtr);
  78. } /* EntryPoint */
  79.  
  80. /* The Main segment.  This is placed immediately after EntrySeg in the XCMD. */
  81. segment "Main";
  82. pascal void XWindShell(paramPtr)
  83. XCMDPtr paramPtr;
  84. {
  85.     /* The main routine of the XCMD.  Most XWindow XCMDs will have a fairly small
  86.        main routine with the majority of the bulk of the XCMD in the routines
  87.        dispatched to by the HandleEvents procedure.  This main routine simply
  88.        deals with calling HandleEvents, displaying Help or Copyright notices,
  89.        and the initial creation of the XWindow. */
  90.     
  91.     #define kLeftPos    100        /* Window coordinates in 640 coordinates */
  92.     #define kTopPos        50
  93.     #define kWindWidth    250
  94.     #define kWindHeight    60
  95.  
  96.     int            pCount; 
  97.     WindowPtr    xWindow;
  98.     Rect        windRect;
  99.  
  100.       char    *copyrightStr     = "\pAnswer \"XWindShell XCMD v1.0\" & return & \"by Darin Acquistapace, 1/29/92\" & return & \"© 1992 Apple Computer, Inc.\"";
  101.       char    *helpStr         = "\pAnswer \"FORM:  XWindShell\"";
  102.     char    *wrongVersionStr = "\pXWindShell XCMD requires HyperCard IIGS 1.1";
  103.     char    *createErrStr     = "\pUnable to create window";
  104.     char    *windTitle         = "\pSampleXWindow";
  105.  
  106.       Str255    str;
  107.     
  108.     /* Get the memory ID to be used for all calls to the memory manager.  This
  109.        ID will be unique to _each_ XWindow. */
  110.     memoryID = paramPtr->userID;
  111.     pCount = paramPtr->paramCount;
  112.     gParamPtr = paramPtr;
  113.     
  114.     /* If the paramCount is negative, we have been called in response to an event. */
  115.     if (pCount < 0) {
  116.       HandleEvents();
  117.       return;
  118.     }
  119.  
  120.     /* Display help or copyright info in response to "?" or "!". */
  121.     if (pCount == 1) {
  122.       ZeroToPas(*(paramPtr->params[0]), &str);
  123.       if (str.text[0] == '!') {
  124.         SendHCMessage(copyrightStr);
  125.         return;
  126.       }
  127.       if (str.text[0] == '?') {
  128.         SendHCMessage(helpStr);
  129.         return;
  130.       }
  131.     }
  132.     
  133.     /* Make sure we are running at least version 1.1 of HyperCard IIGS. */
  134.     if (! CorrectVersion()) {
  135.       ReturnResult(wrongVersionStr);
  136.       return;
  137.     }
  138.  
  139.     /* Check for the desired number of parameters.  XCMDs with optional
  140.        parameters will need to check the paramCount for being within a 
  141.        certain range.  Only scripting errors such as an invalid paramCount
  142.        should generate a HyperTalk error.  Other problems such as invalid or
  143.        out-of-range data in the parameters should be handled by returning an
  144.        appropriate error string the the result. */
  145.     if (pCount != 0) {
  146.       HTError();
  147.       return;
  148.     }
  149.         
  150.     /* Here the XCMD should process any parameters required.  See the other
  151.        sample XCMDs for examples of using the ZeroToPas and other conversion
  152.        callbacks to convert the zero-terminated input parameters into other
  153.        forms. */
  154.  
  155.     /* Create the XWindow invisible.  We'll show it after we perform any 
  156.        needed initialization on it, such as creating controls, etc. */
  157.     SetRect(&windRect, kLeftPos, kTopPos, kLeftPos + kWindWidth, kTopPos + kWindHeight);
  158.     xWindow = NewXWindow(&windRect, windTitle, false, xWindoidStyle);        
  159.     if (xWindow == nil) {
  160.       ReturnResult(createErrStr);
  161.       return;
  162.     }
  163.       
  164.     /* Create the contents for the window */
  165.     SetPort(xWindow);
  166.     SetUpContents(xWindow);
  167.  
  168.     /* Display the window.  This will generate an update event which will be sent
  169.        immediately following the xOpenEvt. */
  170.     ShowWindow(xWindow);
  171. } /* XWindShell */
  172.  
  173.  
  174. /* -------------------------------------------------------------------------- */
  175. void ReturnResult(str)
  176. /* Puts the specified string into the result and terminates. */
  177. Str255 *str;
  178. {
  179.   gParamPtr->returnValue = PasToZero(str);
  180. } /* ReturnResult */
  181.  
  182.  
  183. /* -------------------------------------------------------------------------- */
  184. void HTError()
  185. /* Generates a HyperTalk error dialog box complete with Script and Cancel 
  186.    buttons. */
  187. {
  188.   char    *ScriptErrStr    = "\pCan't understand arguments of XCMD XWindShell.";
  189.  
  190.   gParamPtr->returnStat = 1;
  191.   ReturnResult(ScriptErrStr);
  192. } /* HTError */
  193.  
  194.  
  195. /* -------------------------------------------------------------------------- */
  196. void MyDisposeHandle(h)
  197. /* Checks a handle for NIL before disposing of it.  A good practice. */
  198. Handle h;
  199. {
  200.   if (h != nil) DisposeHandle(h);
  201. } /* MyDisposeHandle */
  202.  
  203.  
  204. /* -------------------------------------------------------------------------- */
  205. void CleanUpMemory(whichWindow)
  206. /* Free all memory associated with the XWindow.  This could be a handle
  207.    referenced by the GetXWindowValue callback. */
  208. WindowPtr whichWindow;
  209. {
  210. } /* CleanUpMemory */
  211.  
  212.  
  213. /* -------------------------------------------------------------------------- */
  214. void HandleWindowClick(whichWindow, ourEvent)
  215. /* A mouseDown event has occurred in our window.  This procedure handles
  216.    tracking the click and taking whatever actions are necessary as a result
  217.    of the click. Tracking controls in XWindows is no different than doing
  218.    the same in any standard window.  FindControl and TrackControl would be
  219.    commonly used to track the click.  See the Picture and ListWindow sample
  220.    XCMDs for examples of using the control manager to handle these actions. */
  221. WindowPtr     whichWindow;
  222. EventRecord    ourEvent;
  223. {
  224. } /* HandleWindowClick */
  225.  
  226.  
  227. /* -------------------------------------------------------------------------- */
  228. void ProcessIdle(whichWindow)
  229. /* Take any actions that need to be performed periodically.  This procedure
  230.    will only be called if the SetXWIdleTime callback has been called with
  231.    an interval value other than zero (the default.) */
  232. WindowPtr whichWindow;
  233. {
  234. } /* ProcessIdle */
  235.  
  236.  
  237. /* -------------------------------------------------------------------------- */
  238. void HandleOpenEvent(whichWindow)
  239. /* Perform any actions necessary before any other events are sent.  At this
  240.    point, the window is created and visible. */
  241. WindowPtr     whichWindow;
  242. {
  243.   /* Allow reentrancy, if this is not set, the XWindow may lose events that
  244.      occur because of events instigated by the XCMD.  For instance, if the
  245.      mouseDown handler performs some action which causes HyperCard to close
  246.      the XWindow, the xCloseEvt will not be received because the XCMD has the
  247.      code in the mouseDown handler pending and will be returned to when Hyper-
  248.      Card finishes executing whatever task the mouseDown handler began.  This
  249.      can be set to true for both types of events in most XCMDs and set to false
  250.      temporarily if the need arises to temporarily halt recursive calls to the
  251.      XCMD. 
  252.     
  253.      If an XCMD wishes to recieve null events, it should call SetXWIdleTime
  254.      at this point with an interval other than zero. */
  255.   XWAllowReEntrancy(whichWindow, true, true);
  256. } /* HandleOpenEvent */
  257.  
  258.  
  259. /* -------------------------------------------------------------------------- */
  260. void HandleCursorWithin(whichWindow, cursorLoc)
  261. /* The mouse cursor is within the XWindow, perform any actions necessary,
  262.    such as changing the cursor shape. */
  263. {
  264.   /* Setting the passFlag to true tells HyperCard that we would like it
  265.      to handle changing the cursor to an arrow when the cursor is within
  266.      the XWindow just as it does for the built-in windows. */
  267.   gParamPtr->passFlag = true;
  268. } /* HandleCursorWithin */
  269.  
  270.  
  271. /* -------------------------------------------------------------------------- */
  272. void HandleHideShow(hideFlag)
  273. /* An XCMD has called either the HideHCPalettes or ShowHCPalettes callbacks
  274.    and our visible status has changed.  An XCMD may wish to deallocate memory
  275.    used for updating the XWindow if it knows it will be hidden for a period of
  276.    time.  An example usage would be if a significant amount of memory was
  277.    required to maintain the contents of an XWindow.  A script could call an
  278.    XCMD to send the HidePalettes event when the user entered the paint tools
  279.    so that the XCMD could free what memory it could to provide more memory
  280.    for the paint buffers. */
  281. Boolean hideFlag;
  282. {
  283. } /* HandleHideShow */
  284.  
  285.  
  286. /* -------------------------------------------------------------------------- */
  287. void HandleEvents()
  288. /* Handle events specific to our XWindow.  HyperCard will only send events
  289.    to the XCMD pertaining to windows it has opened.  The XCMD, however, 
  290.    should not assume that it owns only one window.  Subsequent calls to
  291.    the XCMD to create the XWindow will result in one XCMD code segment
  292.    owning multiple XWindows. This routine is similar to the main event loop
  293.    of an application, all events dealing with the XWindows the XCMD has
  294.    created will be sent here and dispatched to the appropriate routine to
  295.    respond to them. */
  296. {
  297.   XWEventInfoPtr    myEventInfo;
  298.   WindowPtr            window;
  299.   EventRecord        event;
  300.  
  301.   myEventInfo = (XWEventInfoPtr) gParamPtr->params[0];
  302.   window = myEventInfo->eventWindow;
  303.   event = myEventInfo->event;
  304.   
  305.   switch (event.what) {
  306.     case    nullEvt:            ProcessIdle(window);
  307.                                 break;
  308.     case    xOpenEvt:            HandleOpenEvent(window);
  309.                                 break;
  310.     case    updateEvt:            UpdateXWindow(window);
  311.                                 break;
  312.     case    mouseDownEvt:        HandleWindowClick(window, event);
  313.                                 break;
  314.     case    xHidePalettesEvt:
  315.     case    xShowPalettesEvt:    HandleHideShow(event.what == xHidePalettesEvt);
  316.                                 break;
  317.     case    xCloseEvt:            CleanUpMemory(window);
  318.                                 break;
  319.     case    xCursorWithin:        HandleCursorWithin(window, event.where);
  320.                                 break;
  321.   }
  322. } /* HandleEvents */
  323.  
  324.  
  325. /* -------------------------------------------------------------------------- */
  326. void SetUpContents(whichWindow)
  327. /* Our window has been created via a call to the NewXWindow callback and is
  328.    invisible.  Now handle any initialization necessary for the XWindow such as 
  329.    calling NewControl, etc. */
  330. WindowPtr whichWindow;
  331. {
  332. } /* SetUpContents */
  333.  
  334.  
  335. /* -------------------------------------------------------------------------- */
  336. void UpdateXWindow(whichWindow)
  337. /* Handles updating the contents of the XWindow.  This may include drawing 
  338.    a background picture, calling DrawControls, etc.  HyperCard takes care of 
  339.    calling BeginUpdate and EndUpdate for you. This routine should only update 
  340.    the window.  Be careful not to do anything that might cause another update 
  341.    event to occur which would result in recursion. */
  342. WindowPtr whichWindow;
  343. {
  344. } /* UpdateXWindow */
  345.  
  346.  
  347. /* -------------------------------------------------------------------------- */
  348. Boolean CorrectVersion()
  349. /* Returns true if the version of HyperCard IIGS currently running is greater
  350.    than or equal to the string "1.1". Note that we're performing the check
  351.    by simply checking the first digit after the decimal point.  This is
  352.    reasonable since the only value that should fail is zero. */
  353. {
  354. Handle    tempHandle;
  355. Str255     tempStr;
  356.  
  357.   tempHandle = EvalExpr("\pthe version");
  358.   ZeroToPas(*tempHandle, &tempStr);
  359.   MyDisposeHandle(tempHandle);
  360.   return ( (byte) tempStr.text[2] >= 49);
  361.  
  362. }